package com.igo.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.igo.domain.datacollection.devicedata.DeviceData;
import com.igo.domain.datacollection.devicedata.DeviceInfo;
import com.igo.domain.datacollection.devicedata.FlatCarData;
import com.igo.domain.datacollection.devicedata.GantryCraneCaData;
import com.igo.mapper.devicedata.DeviceDataMapper;
import com.igo.mapper.devicedata.DeviceInfoMapper;
import com.igo.mapper.devicedata.FlatCarDataMapper;
import com.igo.mapper.devicedata.GantryCraneCaDataMapper;
import com.igo.service.devicedata.FlatCarDataService;
import com.igo.service.devicedata.GantryCraneCaDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

@Service
public class DeviceCrashData {

    private ExecutorService es = Executors.newFixedThreadPool(2000);

    @Resource
    private DeviceDataMapper deviceDataMapper;

    @Resource
    private DeviceInfoMapper deviceInfoMapper;

    @Resource
    private FlatCarDataService flatCarDataService;

    @Resource
    private FlatCarDataMapper flatCarDataMapper;

    @Autowired
    private GantryCraneCaDataMapper gantryCraneCaDataMapper;

    @Resource
    private GantryCraneCaDataService gantryCraneCaDataService;

    /**
     * 按时间生成结构化数据(可配置性)
     */

    public void crashData(Date startTime, Date endTime) throws InterruptedException {
        //平板车数据
        List<FlatCarData> insertFlatCarDataList = new ArrayList<>();
        //门吊数据
        List<GantryCraneCaData> insertGantryCraneCaDataList = new ArrayList<>();
        //设备信息
        List<DeviceInfo> deviceInfos = deviceInfoMapper.selectList(new LambdaQueryWrapper<DeviceInfo>());
        List<FlatCarData> flatCarOrgins = flatCarDataMapper
                .selectList(new LambdaQueryWrapper<FlatCarData>()
                        .select(FlatCarData::getOriginDataId)
                        .eq(FlatCarData::getRunningState,"1")
                        .ge(FlatCarData::getCreateTime, startTime).le(FlatCarData::getCreateTime, endTime)
                .groupBy(FlatCarData::getOriginDataId));
        List<GantryCraneCaData> gantryCraneCaOrgins = gantryCraneCaDataMapper
                .selectList(new LambdaQueryWrapper<GantryCraneCaData>()
                        .select(GantryCraneCaData::getOriginDataId)
                        .eq(GantryCraneCaData::getRunningState,"1")
                        .ge(GantryCraneCaData::getCreateTime, startTime).le(GantryCraneCaData::getCreateTime, endTime)
                        .groupBy(GantryCraneCaData::getOriginDataId));
        List<String> flatCarOrginList = flatCarOrgins.stream().map(FlatCarData::getOriginDataId).collect(Collectors.toList());
        List<String> gantryCraneCaList = gantryCraneCaOrgins.stream().map(GantryCraneCaData::getOriginDataId).collect(Collectors.toList());
        List<Callable<Void>> tasks = new ArrayList<>();
        //根据时间段查询实时数据库
        List<DeviceData> deviceDataList = deviceDataMapper
                .selectList(new LambdaQueryWrapper<DeviceData>()
                        .ge(DeviceData::getCreateTime, startTime).le(DeviceData::getCreateTime, endTime)
                        .select(DeviceData::getDeviceNo, DeviceData::getModelField, DeviceData::getModelVal, DeviceData::getOriginDataId, DeviceData::getCreateTime));
        //时间段查询入库
        for (;startTime.compareTo(endTime) == -1; startTime = DateUtil.offsetHour(startTime, 2)) {
            Date start = startTime;
            Date end = DateUtil.offsetHour(startTime,2);
            List<DeviceData> deviceDataTimeList = deviceDataList.stream()
                    .filter(deviceData -> deviceData.getCreateTime().compareTo(start) >= 0 && deviceData.getCreateTime().compareTo(end) <0).collect(Collectors.toList());
            //分组id集合
            List<String> dataOriginList = deviceDataTimeList.stream().map(DeviceData::getOriginDataId).distinct().collect(Collectors.toList());
            //根据实时数据表建表
            dataOriginList.stream().forEach(dataOrigin->{
//            for (String dataOrigin : dataOriginList) {
                List<DeviceData> deviceDataOrigin = deviceDataTimeList.stream()
                        .filter(deviceData -> deviceData.getOriginDataId().equals(dataOrigin)).collect(Collectors.toList());
                DeviceInfo device = deviceInfos.stream()
                        .filter(deviceInfo -> deviceInfo.getDeviceNo().equals(deviceDataOrigin.get(0).getDeviceNo())).findFirst().orElse(null);
                GantryCraneCaData gantryCraneCaData = new GantryCraneCaData();
                FlatCarData flatCarData = new FlatCarData();
//                tasks.add(() -> {
                deviceDataOrigin.stream().forEach(deviceData -> {
                    //当前数据为平板车数据
                    if (device!=null && device.getProductId().compareTo(2) == 0) {
                        flatCarData.setDeviceNo(deviceData.getDeviceNo());
                        if (deviceData.getModelField().equals("voltage") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            flatCarData.setVoltage(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("current") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            flatCarData.setCurrent(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("loadCapacity") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            flatCarData.setLoadCapacity(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("oilQuantity") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            flatCarData.setOilQuantity(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("longitude") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            flatCarData.setLongitude(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("latitude") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            flatCarData.setLatitude(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("runningState") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            flatCarData.setRunningState(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("hydraulicCylinderPressure1") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            flatCarData.setHydraulicCylinderPressure1(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("hydraulicCylinderPressure2") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            flatCarData.setHydraulicCylinderPressure2(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("hydraulicCylinderPressure3") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            flatCarData.setHydraulicCylinderPressure3(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("hydraulicCylinderPressure4") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            flatCarData.setHydraulicCylinderPressure4(deviceData.getModelVal());
                        }
                        flatCarData.setCreateTime(deviceData.getCreateTime());
                        flatCarData.setDataTime(deviceData.getCreateTime());
                        flatCarData.setOriginDataId(dataOrigin);
                    } else if (device!=null && device.getProductId().compareTo(3) == 0) {//当前数据为门吊数据
                        gantryCraneCaData.setDeviceNo(deviceData.getDeviceNo());
                        if (deviceData.getModelField().equals("voltage") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            gantryCraneCaData.setVoltage(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("current") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            gantryCraneCaData.setCurrent(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("windSpeed") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            gantryCraneCaData.setWindSpeed(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("correctionValue") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            gantryCraneCaData.setCorrectionValue(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("longitude") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            gantryCraneCaData.setLongitude(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("latitude") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            gantryCraneCaData.setLatitude(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("runningState") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            gantryCraneCaData.setRunningState(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("loadCapacityValue1") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            gantryCraneCaData.setLoadCapacityValue1(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("loadCapacityValue2") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            gantryCraneCaData.setLoadCapacityValue2(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("loadCapacityValue3") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            gantryCraneCaData.setLoadCapacityValue3(deviceData.getModelVal());
                        }
                        if (deviceData.getModelField().equals("loadCapacityValue4") && StringUtils.isNotBlank(deviceData.getModelVal())) {
                            gantryCraneCaData.setLoadCapacityValue4(deviceData.getModelVal());
                        }

                        gantryCraneCaData.setCreateTime(deviceData.getCreateTime());
                        gantryCraneCaData.setDataTime(deviceData.getCreateTime());
                        gantryCraneCaData.setOriginDataId(dataOrigin);

                    }

                });

                if (StringUtils.isNotBlank(gantryCraneCaData.getDeviceNo()) && !gantryCraneCaList.contains(gantryCraneCaData.getOriginDataId())) {
                    insertGantryCraneCaDataList.add(gantryCraneCaData);
                }
                if (StringUtils.isNotBlank(flatCarData.getDeviceNo()) && !flatCarOrginList.contains(flatCarData.getOriginDataId())) {
                    insertFlatCarDataList.add(flatCarData);
                }

//                        return null;
//                    });

//            }
            });
//            es.invokeAll(tasks); // 等待所有子线程的任务执行完毕
        }

        insertGantryCraneCaDataList.stream().forEach(gantryCraneCaData -> {
            BigDecimal sumLoadCapacity= new BigDecimal("0");
            if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(gantryCraneCaData.getLoadCapacityValue1())){
                try {
                    BigDecimal loadCapacityValue1 = new BigDecimal(gantryCraneCaData.getLoadCapacityValue1());
                    sumLoadCapacity=sumLoadCapacity.add(loadCapacityValue1);
                }catch (NumberFormatException e){
                    //过滤错误数据
                }
            }
            if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(gantryCraneCaData.getLoadCapacityValue2())){
                try {
                    BigDecimal loadCapacityValue2 = new BigDecimal(gantryCraneCaData.getLoadCapacityValue2());
                    sumLoadCapacity=sumLoadCapacity.add(loadCapacityValue2);
                }catch (NumberFormatException e){
                    //过滤错误数据
                }
            }
            if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(gantryCraneCaData.getLoadCapacityValue3())){
                try {
                    BigDecimal loadCapacityValue3 = new BigDecimal(gantryCraneCaData.getLoadCapacityValue3());
                    sumLoadCapacity=sumLoadCapacity.add(loadCapacityValue3);
                }catch (NumberFormatException e){
                    //过滤错误数据
                }
            }
            if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(gantryCraneCaData.getLoadCapacityValue4())){
                try {
                    BigDecimal loadCapacityValue4 = new BigDecimal(gantryCraneCaData.getLoadCapacityValue4());
                    sumLoadCapacity=sumLoadCapacity.add(loadCapacityValue4);
                }catch (NumberFormatException e){
                    //过滤错误数据
                }
            }
            gantryCraneCaData.setLoadCapacity(sumLoadCapacity);

        });

        if (CollectionUtil.isNotEmpty(insertFlatCarDataList)) {
            List<FlatCarData> list = insertFlatCarDataList.stream().filter(insertFlatCarData -> insertFlatCarData != null).collect(
                    // 使用 Collectors.collectingAndThen 收集器，将流中的元素收集为一个列表
                    Collectors.collectingAndThen(
                            // 使用 Collectors.toCollection 收集器，将元素收集到一个 TreeSet 中
                            Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(FlatCarData::getOriginDataId))),
                            // 使用 ArrayList::new 将 TreeSet 转换为 ArrayList
                            ArrayList::new
                    )
            );
            list.stream().filter(insertFlatCarData->insertFlatCarData!=null)
                    .forEach(insertFlatCarData-> {
                        insertFlatCarData.setId(IdUtils.simpleUUID());
                        insertFlatCarData.setDelFlag("0");

                    });
            flatCarDataService.saveBatch(list);
        }
        if (CollectionUtil.isNotEmpty(insertGantryCraneCaDataList)) {
            List<GantryCraneCaData> list = insertGantryCraneCaDataList.stream().filter(insertGantryCraneCaData -> insertGantryCraneCaData != null).collect(
                    // 使用 Collectors.collectingAndThen 收集器，将流中的元素收集为一个列表
                    Collectors.collectingAndThen(
                            // 使用 Collectors.toCollection 收集器，将元素收集到一个 TreeSet 中
                            Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(GantryCraneCaData::getOriginDataId))),
                            // 使用 ArrayList::new 将 TreeSet 转换为 ArrayList
                            ArrayList::new
                    )
            );
            list.stream().filter(insertGantryCraneCaData->insertGantryCraneCaData!=null)
                    .forEach(insertGantryCraneCaData-> {
                        insertGantryCraneCaData.setId(IdUtils.simpleUUID());
                        insertGantryCraneCaData.setDelFlag("0");

                    });
            gantryCraneCaDataService.saveBatch(list);
        }
    }
}
